package com.shop.service.module.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shop.service.module.entity.GoodsEntity;
import com.shop.service.module.entity.Result;
import com.shop.service.module.entity.TeamEntity;
import com.shop.service.module.mapper.AddressMapper;
import com.shop.service.module.mapper.TeamMapper;
import com.shop.service.module.mapper.TeamUserMapper;
import com.shop.service.module.service.BaseService;
import com.shop.service.module.service.TeamService;
import com.shop.service.module.util.RedisLockHelper;
import org.checkerframework.checker.units.qual.A;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.Queue;

@Service
public class TeamServiceImpl extends ServiceImpl<TeamMapper, TeamEntity> implements TeamService {
    @Autowired
    private RedisLockHelper redisLockHelper;
    @Autowired
    private AddressMapper addressMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private TeamUserMapper teamUserMapper;

    @Override
    public Result getListForPage(int pno, int psize, String name, Integer isOnSale, Integer type) {
        Page<TeamEntity> p = new Page<>(pno, psize);
        Page<TeamEntity> result = baseMapper.getListForPage(p, name, isOnSale, type);
        JSONObject data = new JSONObject();
        JSONObject jsonResult = new JSONObject();
        jsonResult.put("pno", pno);
        jsonResult.put("psize", psize);
        jsonResult.put("pCount", result.getPages());
        jsonResult.put("totalElements", result.getTotal());
        data.put("list", result.getRecords());
        data.put("page", jsonResult);
        return Result.end(200, data, "查询成功");
    }

    @Override
    public void makeActivityTimeout(Long id) {
        TeamEntity team = baseMapper.selectById(id);
        if (team != null) {
            team.setStatus(1);
            baseMapper.updateById(team);
        }
    }

    @Override
    public Result insertTeam(Long id, String userId) {
        //设置锁的名称为 team+活动id保证每个活动的锁都是单独的
        String lockKey = "team" + id;
        //尝试抢锁
        boolean lock = redisLockHelper.lock(lockKey);
        //设置最大重试五次
        int tryLockCount = 5;
        while (lock == false && tryLockCount > 0) {
            lock = redisLockHelper.lock(lockKey);
            tryLockCount--;

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
        //判断如果尝试5次还没有结果就返回错误信息并释放锁
        if (lock == false) {
            return Result.end(500, "", "当前活动人数较多，请重试");
        }
//抢到锁之后先检查内存中是否存在活动信息
        //定义在redis中保存活动数据的key
        String teamDataKey = "team_data_" + id;
        //尝试从redis中获取活动数据
        TeamEntity teamData = (TeamEntity) redisTemplate.opsForValue().get(teamDataKey);
        //如果没有则查询数据库
        if (teamData == null) {
            teamData = baseMapper.selectById(id);
        }
        //判断当前的活动状态是否是0，代表是否是进行中的活动
        System.out.println("teamData.getSize()=>"+teamData.getSize());
        if (teamData.getStatus() != 0) {
            //释放锁
            redisLockHelper.delete(lockKey);
            return Result.end(500, "", "活动已过期或拼满");
        }
        //判断当前的活动参与人数是否已经达到了活动容量
        if (teamData.getHasMember() >= teamData.getSize()) {
            //设置活动状态为以拼满
            teamData.setStatus(2);
            //释放锁
            redisLockHelper.delete(lockKey);
            return Result.end(500, "", "活动以拼满");
        }
        //判断当付钱的用户是否存在收货地址
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("is_default", 1);
        queryWrapper.eq("user_id", userId);
        List list = addressMapper.selectList(queryWrapper);
        if (list.size() == 0) {
            //释放锁
            redisLockHelper.delete(lockKey);
            return Result.end(500, "", "您还没有配置默认收货地址，请设置");

        }
        //检查当前用户是否存在该活动
        QueryWrapper q0 = new QueryWrapper();
        q0.eq("user_id", userId);
        q0.eq("team_id", id);
        List teamList = teamUserMapper.selectList(q0);
        if (teamList.size() > 0) {
            //释放锁
            redisLockHelper.delete(lockKey);
            return Result.end(500, "", "您已经参加过该活动");
        }
        //全部验证后扣减内存中的活动库存,相当于增加一个参与人
        Integer hansMemberCount = teamData.getHasMember();
        teamData.setHasMember(hansMemberCount + 1);
        redisTemplate.opsForValue().getAndSet(teamDataKey, teamData);
        //扣减库存之后通知消息队列
        JSONObject data = new JSONObject();
        //封装参数 活动id和用户id
        data.put("id", id);
        data.put("userId", userId);
        // 通知消息队列处理复杂的创建订单业务
        rabbitTemplate.convertAndSend(
                "orderExchange",
                "orderRouter",
                data);
        //释放锁
        redisLockHelper.delete(lockKey);
        //返回参与成功数据
        return Result.end(200, "", "活动参与成功,等待订单生成");

    }

    @Override
    public Result getResult(Long id, String userId) {
        String teamKey = "team"+id+userId;
        Object res = redisTemplate.opsForValue().get(teamKey);
        if(res == null){
            return Result.end(101,"","订单生成中");
        }else{
            return Result.end(200,"","订单创建成功请在15分钟内完成支付");
        }
    }
}
